package visualizer.graphics;

import processing.core.PImage;

public class MagicWand {
	private int treshold;
	
	public MagicWand(int treshold)
	{
		this.treshold = treshold;
	}
	
	public Mask select(Point start, PImage image)
	{
		Mask result = new Mask();
		image.loadPixels();
		int selectColor = image.pixels[start.y * image.width + start.x];
		flood(result, selectColor, image, start);
		return result;
	}
	
	protected void flood(Mask result, int selectColor, PImage image, Point p)
	{
		result.add(p);
		
		int color;
		int difference;
		
		int pdx = 0;
		int pdy = 0;
		
		difference = 0;
		do {
			pdx++;
			color = image.get(p.x + pdx, p.y);
			difference += getDifference(selectColor, color);
		}
		while ((difference <= treshold) && result.add(new Point(p.x + pdx, p.y)));
		
		difference = 0;
		do {
			pdy++;
			color = image.get(p.x, p.y + pdy);
			difference += getDifference(selectColor, color);
		}
		while ((difference <= treshold) && result.add(new Point(p.x, p.y + pdy)));
		
		int ndx = 0;
		int ndy = 0;
		
		difference = 0;
		do {
			ndx--;
			color = image.get(p.x + ndx, p.y);
			difference += getDifference(selectColor, color);
		}
		while ((difference <= treshold) && result.add(new Point(p.x + ndx, p.y)));
		
		difference = 0;
		do {
			ndy--;
			color = image.get(p.x, p.y + ndy);
			difference += getDifference(selectColor, color);
		}
		while ((difference <= treshold) && result.add(new Point(p.x, p.y + ndy)));
		
		while (--pdx != 0) {
			flood(result, selectColor, image, new Point(p.x + pdx, p.y));
		}
		while (++ndx != 0) {
			flood(result, selectColor, image, new Point(p.x + ndx, p.y));
		}
		
		while (--pdy != 0) {
			flood(result, selectColor, image, new Point(p.x, p.y + pdy));
		}
		while (++ndy != 0) {
			flood(result, selectColor, image, new Point(p.x, p.y + ndy));
		}
	}
	
	private int getDifference(int a, int b)
	{
		return Math.abs(((a >> 16) & 255) - ((b >> 16) & 255))
		     + Math.abs(((a >> 8) & 255) - ((b >> 8) & 255))
		     + Math.abs((a & 255) - (b & 255));
	}
	
}
